home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / ds5000.md / devSCSIC90.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  50KB  |  1,811 lines

  1. /* 
  2.  * devSCSIC90.c --
  3.  *
  4.  *    Routines specific to the SCSI NCR 53C9X Host Adaptor.  This adaptor is
  5.  *    based on the NCR 53C90 chip.
  6.  *    The 53C90 supports connect/dis-connect.
  7.  *
  8.  * Copyright 1988 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/ds5000.md/devSCSIC90.c,v 1.10 92/07/13 17:47:33 mottsmth Exp $ SPRITE (Berkeley)";
  20. #endif /* not lint */
  21.  
  22. #include "sprite.h"
  23. #include "scsiC90.h"
  24. #include "mach.h"
  25. #include "dev.h"
  26. #include "scsiHBA.h"
  27. #include "scsiDevice.h"
  28. #include "sync.h"
  29. #include "stdio.h"
  30. #include "stdlib.h"
  31. #include "string.h"
  32. #include "bstring.h"
  33. #include "devSCSIC90.h"
  34. #include "devSCSIC90Int.h"
  35.  
  36. /*
  37.  * Forward declarations.  
  38.  */
  39.  
  40. static void        PrintMsg _ARGS_ ((unsigned int msg));
  41. static void        PrintPhase _ARGS_ ((unsigned int phase));
  42. static void        PrintLastPhase _ARGS_ ((unsigned int phase));
  43. static ReturnStatus     SendCommand _ARGS_ ((Device *devPtr,
  44.                                              ScsiCmd *scsiCmdPtr));
  45. static void             PrintRegs _ARGS_((volatile CtrlRegs *regsPtr));
  46. static void             PerformCmdDone _ARGS_((Controller *ctrlPtr,
  47.                            ReturnStatus status));
  48. static ReturnStatus     PerformSelect _ARGS_((Controller *ctrlPtr,
  49.                           unsigned int interruptReg,
  50.                           unsigned int sequenceReg));
  51. static ReturnStatus     PerformDataXfer _ARGS_((Controller *ctrlPtr,
  52.                           unsigned int interruptReg,
  53.                           unsigned int statusReg));
  54. static ReturnStatus     PerformStatus _ARGS_((Controller *ctrlPtr,
  55.                           unsigned int interruptReg));
  56. static ReturnStatus     PerformMsgIn _ARGS_(( Controller *ctrlPtr));
  57. static ReturnStatus     PerformReselect _ARGS_(( Controller *ctrlPtr,
  58.                           unsigned int interruptReg));
  59. static ReturnStatus     PerformExtendedMsgIn _ARGS_(( Controller *ctrlPtr,
  60.                           unsigned int message));
  61. static int              SpecialSenseProc _ARGS_((ScsiCmd *scsiCmdPtr,
  62.                         ReturnStatus status,
  63.                         int statusByte,
  64.                         int byteCount,
  65.                         int senseLength,
  66.                         Address senseDataPtr));
  67. static void             PutCircBuf _ARGS_((int type, char *object));
  68.  
  69. /*
  70.  * devSCSIC90Debug - debugging level
  71.  *    2 - normal level
  72.  *    4 - one print per command in the normal case
  73.  *    5 - traces interrupts
  74.  */
  75. int devSCSIC90Debug = 2;
  76. Controller *Controllers[MAX_SCSIC90_CTRLS];
  77.  
  78. char        circBuf[CIRCBUFLEN] = {""};
  79. int         circHead = 0;
  80. char numTab[16] = {
  81.     '0', '1', '2', '3', '4', '5', '6', '7',
  82.     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
  83.     };
  84.      
  85.  
  86.  
  87. /*
  88.  *----------------------------------------------------------------------
  89.  *
  90.  * SendCommand --
  91.  *
  92.  *      Send a command to a SCSI controller.
  93.  *    NOTE: The caller is assumed to have the master lock of the controller
  94.  *    to which the device is attached held.
  95.  *      
  96.  *
  97.  * Results:
  98.  *    An error code.
  99.  *
  100.  * Side effects:
  101.  *    Those of the command (Read, write etc.)
  102.  *
  103.  *----------------------------------------------------------------------
  104.  */
  105. static ReturnStatus
  106. SendCommand(devPtr, scsiCmdPtr)
  107.     Device     *devPtr;        /* Device to sent to. */
  108.     ScsiCmd    *scsiCmdPtr;        /* Command to send. */
  109. {
  110.     volatile CtrlRegs    *regsPtr; /* Host Adaptor registers */
  111.     char    *charPtr;
  112.     Controller    *ctrlPtr;
  113.     int i;
  114.     int size;                /* Number of bytes to transfer */
  115.  
  116.     /*
  117.      * Set current active device and command for this controller.
  118.      */
  119.     ctrlPtr = devPtr->ctrlPtr;
  120.     regsPtr = ctrlPtr->regsPtr;
  121.  
  122.     if (ctrlPtr->devPtr != (Device *)NIL) {
  123.     panic("SCSIC90Command: can't send: host is busy\n");
  124.     }
  125.  
  126.     SET_CTRL_BUSY(ctrlPtr,devPtr);
  127.     SET_DEV_BUSY(devPtr, scsiCmdPtr);
  128.  
  129.     devPtr->scsiCmdPtr   = scsiCmdPtr;
  130.     size = scsiCmdPtr->bufferLen;
  131.     if (size == 0) {
  132.     devPtr->dmaState = DMA_INACTIVE;
  133.     } else {
  134.     devPtr->dmaState = (scsiCmdPtr->dataToDevice) ? DMA_SEND :
  135.                             DMA_RECEIVE;
  136.     }
  137.  
  138.     PUTCIRCBUF(CSTR, "send: targ ");
  139.     PUTCIRCBUF(CBYTE, (char *)devPtr->targetID);
  140.     PUTCIRCBUF(CSTR, ";cmd ");
  141.     PUTCIRCBUF(CINT, (char *)scsiCmdPtr);
  142.     PUTCIRCBUF(CSTR,";buf ");
  143.     PUTCIRCBUF(CINT, (char *)scsiCmdPtr->buffer);
  144.     PUTCIRCBUF(CSTR, ";len ");
  145.     PUTCIRCBUF(CINT, (char *)size);
  146.     PUTCIRCBUF(CSTR,";op ");
  147.     PUTCIRCBUF(CBYTE, (char *)scsiCmdPtr->commandBlock[0]);
  148.     PUTCIRCNULL;
  149.  
  150.     /*
  151.      * SCSI SELECTION.
  152.      */
  153.  
  154.     /*
  155.      * Set phase to selection and command phase so that we know what's happened
  156.      * in the next phase.
  157.      */
  158.     devPtr->lastPhase = PHASE_SELECTION;    /* Selection & command phase.*/
  159.     devPtr->commandStatus = 0;            /* No status yet. */
  160.     devPtr->activeBufPtr = scsiCmdPtr->buffer;
  161.     devPtr->activeBufLen = scsiCmdPtr->bufferLen;
  162.     /* Load select/reselect bus ID register with target ID. */
  163.     regsPtr->scsi_ctrl.write.destID = devPtr->targetID;
  164.     /* Load select/reselect timeout period. */
  165.     regsPtr->scsi_ctrl.write.timeout = SELECT_TIMEOUT;
  166.     /* Zero value for asynchronous transfer. */
  167.     regsPtr->scsi_ctrl.write.synchOffset = devPtr->synchOffset;
  168.     if (devPtr->synchOffset != 0) {
  169.     regsPtr->scsi_ctrl.write.synchPer = devPtr->synchPeriod;
  170.     }
  171.     /* Set the clock conversion register. */
  172.     regsPtr->scsi_ctrl.write.clockConv = CLOCKCONV;
  173.  
  174.     EMPTY_BUFFER();
  175.  
  176.     /* 
  177.      * There are 3 selection possibilities:
  178.      * 1) Without Attention (NATN) which says we don't do disconnect/reselect.
  179.      *    No need to use this anymore.
  180.      * 2) With Attention (ATN) which goes through arbitration, selection
  181.      *    and command phases, announcing that we do disconnect/reselect.
  182.      *    The usual mode.
  183.      * 3) With attention and stop (ATNS) which just goes through 
  184.      *    arbitration and selection phases and stops.  This gives
  185.      *    us a chance to send another message after the IDENTIFY msg
  186.      *    before sending the command.  For use in sending the 1st
  187.      *    message of the synchronous data xfer negotiation.
  188.      */
  189.  
  190.     if (scsiCmdPtr->commandBlockLen != 6 &&
  191.     scsiCmdPtr->commandBlockLen != 10 &&
  192.     scsiCmdPtr->commandBlockLen != 12) {
  193.     printf("%s: Command is wrong length.\n");
  194.     PUTCIRCBUF(CSTR,"send: bad cmd len\n");
  195.     PUTCIRCNULL;
  196.     return DEV_INVALID_ARG;     /* Is this the correct error? */
  197.     }
  198.  
  199.  
  200.     regsPtr->scsi_ctrl.write.FIFO = SCSI_DIS_REC_IDENTIFY | devPtr->handle.LUN;
  201.  
  202.     if ((devPtr->synchPeriod < MIN_SYNCH_PERIOD) &&
  203.     (devPtr->msgFlag & ENABLEEXTENDEDMSG)) {
  204.     devPtr->msgFlag |= REQEXTENDEDMSG;
  205.     EMPTY_BUFFER();
  206.     regsPtr->scsi_ctrl.write.command = CR_SLCT_ATNS;
  207.     PUTCIRCBUF(CSTR,"send ATNS; per ");
  208.     } else {
  209.     /* Load FIFO with 6, 10, or 12 byte scsi command. */
  210.     charPtr = scsiCmdPtr->commandBlock;
  211.     for (i = 0; i < scsiCmdPtr->commandBlockLen; i++) {
  212.         regsPtr->scsi_ctrl.write.FIFO = *charPtr;
  213.         charPtr++;
  214.     }
  215.     PUTCIRCBUF(CSTR,"send ATN; per ");
  216.     EMPTY_BUFFER();
  217.     regsPtr->scsi_ctrl.write.command = CR_SLCT_ATN;
  218.     }
  219.     PUTCIRCBUF(CBYTE,(char *)(devPtr->synchPeriod));
  220.     PUTCIRCBUF(CSTR,"; off ");
  221.     PUTCIRCBUF(CBYTE,(char *)(devPtr->synchOffset));
  222.     PUTCIRCBUF(CSTR,"; cmd ");
  223.     PUTCIRCBUF(CBYTE,(char *)(*scsiCmdPtr->commandBlock));
  224.     PUTCIRCNULL;
  225.  
  226.     return SUCCESS;
  227. }
  228.  
  229.  
  230. /*
  231.  *----------------------------------------------------------------------
  232.  *
  233.  * RequestDone --
  234.  *
  235.  *    Process a request that has finished. Unless a SCSI check condition
  236.  *    bit is present in the status returned, the request call back
  237.  *    function is called.  If check condition is set we fire off a
  238.  *    SCSI REQUEST SENSE to get the error sense bytes from the device.
  239.  *
  240.  * Results:
  241.  *    None.
  242.  *
  243.  * Side effects:
  244.  *    The call back function may be called.
  245.  *
  246.  *----------------------------------------------------------------------
  247.  */
  248.  
  249. static void
  250. RequestDone(devPtr,scsiCmdPtr,status,scsiStatusByte,amountTransferred)
  251.     Device    *devPtr;    /* Device for request. */
  252.     ScsiCmd    *scsiCmdPtr;    /* Request that finished. */
  253.     ReturnStatus status;    /* Status returned. */
  254.     unsigned char scsiStatusByte;    /* SCSI Status Byte. */
  255.     int        amountTransferred; /* Amount transferred by command. */
  256. {
  257.     ReturnStatus    senseStatus;
  258.     Controller            *ctrlPtr = devPtr->ctrlPtr;
  259.     int i;
  260.  
  261.     PUTCIRCBUF(CSTR,"done: targ ");
  262.     PUTCIRCBUF(CBYTE, (char *)devPtr->targetID);
  263.     PUTCIRCBUF(CSTR,";rc ");
  264.     PUTCIRCBUF(CBYTE, (char *)status);
  265.     PUTCIRCBUF(CSTR,";stat ");
  266.     PUTCIRCBUF(CBYTE, (char *)scsiStatusByte);
  267.     PUTCIRCBUF(CSTR,";cnt ");
  268.     PUTCIRCBUF(CBYTE, (char *)amountTransferred);
  269.     PUTCIRCNULL;
  270.  
  271.     SET_CTRL_FREE(ctrlPtr);
  272.  
  273.     /*
  274.      * First check to see if this is the reponse of a HBA-driver generated 
  275.      * REQUEST SENSE command.  If this is the case, we can process
  276.      * the callback of the frozen command for this device and
  277.      * allow the flow of command to the device to be resummed.
  278.      */
  279.     if (scsiCmdPtr->doneProc == SpecialSenseProc) {
  280.     PUTCIRCBUF(CSTR,"sense data:");
  281.     for (i=0; i<amountTransferred; i++) {
  282.         circBuf[circHead] = ' ';
  283.         circHead = (circHead + 1) % CIRCBUFLEN;
  284.         PUTCIRCBUF(CBYTE, (char *)(devPtr->senseBuffer[i]));
  285.     }
  286.     PUTCIRCNULL;
  287.         MASTER_UNLOCK(&(ctrlPtr->mutex));
  288.     (devPtr->frozen.scsiCmdPtr->doneProc)(devPtr->frozen.scsiCmdPtr, 
  289.         SUCCESS,
  290.         devPtr->frozen.statusByte, 
  291.         devPtr->frozen.amountTransferred,
  292.         amountTransferred,
  293.         devPtr->senseBuffer);
  294.          MASTER_LOCK(&(ctrlPtr->mutex));
  295.      SET_DEV_FREE(devPtr);
  296.      return;
  297.     }
  298.     /*
  299.      * This must be an outside request finishing. If the request 
  300.      * suffered an error or the HBA or the scsi status byte
  301.      * says there is no error sense present, we can do the
  302.      * callback and free the controller.
  303.      */
  304.     if ((status != SUCCESS) ||
  305.     (scsiStatusByte != SCSI_STATUS_CHECK)) { 
  306.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  307.     PUTCIRCBUF(CSTR,"done: callback before...");
  308.     (scsiCmdPtr->doneProc)(scsiCmdPtr, status, scsiStatusByte,
  309.                    amountTransferred, 0, (char *) 0);
  310.     MASTER_LOCK(&(ctrlPtr->mutex));
  311.     PUTCIRCBUF(CSTR,"after");
  312.     PUTCIRCNULL;
  313.     SET_DEV_FREE(devPtr);
  314.     return;
  315.     } 
  316.     /*
  317.      * If we got here than the SCSI command came back from the device
  318.      * with the CHECK bit set in the status byte.
  319.      * Need to perform a REQUEST SENSE.  Move the current request 
  320.      * into the frozen state and issue a REQUEST SENSE. 
  321.      */
  322.  
  323.     PUTCIRCBUF(CSTR,"done: issue sense");
  324.     PUTCIRCNULL;
  325.     devPtr->synchPeriod = 0;
  326.     devPtr->synchOffset = 0;
  327.     devPtr->frozen.scsiCmdPtr = scsiCmdPtr;
  328.     devPtr->frozen.statusByte = scsiStatusByte;
  329.     devPtr->frozen.amountTransferred = amountTransferred;
  330.     DevScsiSenseCmd((ScsiDevice *)devPtr, DEV_MAX_SENSE_BYTES, 
  331.             devPtr->senseBuffer, &(devPtr->SenseCmd));
  332.     devPtr->SenseCmd.doneProc = SpecialSenseProc;
  333.     senseStatus = SendCommand(devPtr, &(devPtr->SenseCmd));
  334.     
  335.    /*
  336.      * If we got an HBA error on the REQUEST SENSE we end the outside 
  337.      * command with the SUCCESS status but zero sense bytes returned.
  338.      */
  339.     if (senseStatus != SUCCESS) {
  340.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  341.     (scsiCmdPtr->doneProc)(scsiCmdPtr, status, scsiStatusByte,
  342.                    amountTransferred, 0, (char *) 0);
  343.         MASTER_LOCK(&(ctrlPtr->mutex));
  344.     SET_DEV_FREE(devPtr);
  345.     }
  346.  
  347. }
  348.  
  349. /*
  350.  *----------------------------------------------------------------------
  351.  *
  352.  * DevEntryAvailProc --
  353.  *
  354.  *    Act upon an entry becomming available in the queue for this
  355.  *    controller. This routine is the Dev_Queue callback function that
  356.  *    is called whenever work becomes available for this controller. 
  357.  *    If the controller is not already busy we dequeue and start the
  358.  *    request.
  359.  *    NOTE: This routine is also called from DevSCSIC90Intr to start the
  360.  *    next request after the previously one finishes.
  361.  *
  362.  * Results:
  363.  *    None.
  364.  *
  365.  * Side effects:
  366.  *    Request may be dequeue and submitted to the device. Request callback
  367.  *    function may be called.
  368.  *
  369.  *----------------------------------------------------------------------
  370.  */
  371.  
  372. Boolean
  373. DevEntryAvailProc(clientData, newRequestPtr) 
  374.    ClientData    clientData;    /* Really the Device this request ready. */
  375.    List_Links *newRequestPtr;    /* The new SCSI request. */
  376. {
  377.     Device        *devPtr; 
  378.     Controller         *ctrlPtr;
  379.     ScsiCmd        *scsiCmdPtr = (ScsiCmd *)newRequestPtr;
  380.     ReturnStatus    status;
  381.  
  382.     devPtr = (Device *) clientData;
  383.     ctrlPtr = devPtr->ctrlPtr;
  384.     /*
  385.      * If we are busy (have an active request) just return. Otherwise 
  386.      * start the request.
  387.      */
  388.     
  389.     if ((IS_CTRL_FREE(ctrlPtr)) &&  (IS_DEV_FREE(devPtr))) {
  390.     PUTCIRCBUF(CSTR,"EAP: exec targ ");
  391.     PUTCIRCBUF(CBYTE, (char *)(devPtr->targetID));
  392.     PUTCIRCBUF(CSTR,"; mask ");
  393.     PUTCIRCBUF(CBYTE, (char *)(ctrlPtr->devQueuesMask));
  394.     PUTCIRCBUF(CSTR,"; cmd ptr ");
  395.     PUTCIRCBUF(CINT, (char *)newRequestPtr);
  396.     PUTCIRCNULL;
  397.     } else {
  398.     PUTCIRCBUF(CSTR,"EAP: NQ targ ");
  399.     PUTCIRCBUF(CBYTE, (char *)(devPtr->targetID));
  400.     PUTCIRCBUF(CSTR,"; mask ");
  401.     PUTCIRCBUF(CBYTE, (char *)(ctrlPtr->devQueuesMask));
  402.     PUTCIRCBUF(CSTR,"; cmd ptr ");
  403.     PUTCIRCBUF(CINT,(char *)newRequestPtr);
  404.     PUTCIRCBUF(CSTR,"; intDev ");
  405.     PUTCIRCBUF(CINT,(char *)(ctrlPtr->interruptDevPtr));
  406.     if (ctrlPtr->interruptDevPtr != (Device *)NIL) {
  407.         PUTCIRCBUF(CSTR,"; intDevCmd ");
  408.         PUTCIRCBUF(CINT,(char *)(ctrlPtr->interruptDevPtr->scsiCmdPtr));
  409.     }
  410.     PUTCIRCNULL;
  411.     return FALSE;
  412.     }
  413.  
  414. again:
  415.     scsiCmdPtr = (ScsiCmd *) newRequestPtr;
  416.     devPtr = (Device *) clientData;
  417.     status = SendCommand(devPtr, scsiCmdPtr);
  418.  
  419.     /*    
  420.      * If the command couldn't be started do the callback function.
  421.      */
  422.     if (status != SUCCESS) {
  423.      PUTCIRCBUF(CSTR,"eap: send fail");
  424.      PUTCIRCNULL;
  425.      RequestDone(devPtr,scsiCmdPtr,status,0,0);
  426.      newRequestPtr = Dev_QueueGetNextFromSet(ctrlPtr->devQueues,
  427.                          ctrlPtr->devQueuesMask,
  428.                          &clientData);
  429.     if (newRequestPtr != (List_Links *) NIL) { 
  430.         PUTCIRCBUF(CSTR,"eap: no cmd");
  431.         PUTCIRCNULL;
  432.         goto again;
  433.     } else {
  434.         PUTCIRCBUF(CSTR,"eap: cmd");
  435.         PUTCIRCBUF(CINT,(char *)newRequestPtr);
  436.         PUTCIRCNULL;
  437.     }
  438.     }
  439.  
  440.     return TRUE;
  441.  
  442. }   
  443.  
  444.  
  445. /*
  446.  *----------------------------------------------------------------------
  447.  *
  448.  * DevSCSIC90Intr --
  449.  *
  450.  * Handle interrupts from the SCSI controller.
  451.  *
  452.  * Results:
  453.  *    TRUE if an SCSIC90 controller was responsible for the interrupt
  454.  *    and this routine handled it.
  455.  *
  456.  * Side effects:
  457.  *    Usually a process is notified that an I/O has completed.
  458.  *      Extreme headaches from trying to follow this absurd code.
  459.  * 
  460.  * Note:
  461.  *      Cannot use printf for debugging in this routine since 
  462.  *      printf re-enables interrupts.
  463.  *
  464.  *----------------------------------------------------------------------
  465.  */
  466. Boolean 
  467. DevSCSIC90Intr(clientDataArg)
  468.     ClientData    clientDataArg;
  469. {
  470.     Controller        *ctrlPtr;
  471.     volatile CtrlRegs    *regsPtr;
  472.     Device        *devPtr;
  473.     unsigned char    phase;
  474.     ReturnStatus    status = SUCCESS;
  475.     unsigned char    interruptReg;
  476.     unsigned char    statusReg;
  477.     unsigned char    sequenceReg;
  478.     int                 i;
  479.     char            *charPtr;
  480.     char            tempChar;
  481.  
  482.     ctrlPtr = (Controller *) clientDataArg;
  483.     regsPtr = ctrlPtr->regsPtr;
  484.     devPtr = ctrlPtr->devPtr;
  485.  
  486.     MASTER_LOCK(&(ctrlPtr->mutex));
  487.  
  488.     /* Read registers.
  489.      * reading the interrupt register clears the status and sequence
  490.      * registers so it must be read last.
  491.      */
  492.     statusReg = regsPtr->scsi_ctrl.read.status;
  493.     sequenceReg = regsPtr->scsi_ctrl.read.sequence;
  494.     interruptReg = regsPtr->scsi_ctrl.read.interrupt;
  495.     phase = statusReg & SR_PHASE;
  496.     sequenceReg &= SEQ_MASK;
  497.  
  498.     PUTCIRCBUF(CSTR,"intr: dev ");
  499.     PUTCIRCBUF(CINT,(char *)devPtr);
  500.     PUTCIRCBUF(CSTR,";int ");
  501.     PUTCIRCBUF(CBYTE, (char *)interruptReg);
  502.     PUTCIRCBUF(CSTR,";stat ");
  503.     PUTCIRCBUF(CBYTE, (char *)statusReg);
  504.     PUTCIRCBUF(CSTR,";seq ");
  505.     PUTCIRCBUF(CBYTE, (char *)sequenceReg);
  506.     if (devPtr != (Device *)NIL) {
  507.     PUTCIRCBUF(CSTR,";last ");
  508.     PUTCIRCBUF(CBYTE, (char *)devPtr->lastPhase);
  509.     }
  510.     PUTCIRCNULL;
  511.  
  512. /*    printf("interruptReg 0x%02x, statusReg 0x%02x, sequenceReg 0x%02x\n",
  513.         interruptReg, statusReg, sequenceReg);
  514. */
  515.     /* Check for errors. */
  516.     if (statusReg & SR_GE) {
  517.     panic("gross error 1\n");
  518.     printf("%s: some gross error happened.\n",
  519.         devPtr->handle.locationName);
  520.     status = FAILURE;
  521.     }
  522.     if (statusReg & SR_PE) {
  523.     printf("%s: a parity error happened.\n",
  524.         devPtr->handle.locationName);
  525.     status = FAILURE;
  526.     }
  527.  
  528.     if (interruptReg & IR_SCSI_RST) {
  529.     printf("%s: SCSI reset detected.\n",
  530.         devPtr->handle.locationName);
  531.     status = FAILURE;
  532.     }
  533.     if (interruptReg & IR_ILL_CMD) {
  534.     if (ctrlPtr->interruptDevPtr != (Device *)NIL) {
  535.         PUTCIRCBUF(CSTR,"ignoring illegal cmd interrupt");
  536.         PUTCIRCNULL;
  537.         MASTER_UNLOCK(&(ctrlPtr->mutex));
  538.         return TRUE;
  539.     } else {
  540.         printf("%s: illegal command.\n",
  541.            devPtr->handle.locationName);
  542.         status = FAILURE;
  543.     }
  544.     }
  545.     if (interruptReg & IR_SLCT_ATN) {
  546.     printf("%s: scsi controller selected with ATN which we don't allow.\n",
  547.         devPtr->handle.locationName);
  548.     status = FAILURE;
  549.     }
  550.     if (interruptReg & IR_SLCT) {
  551.     printf("%s: scsi controller selected as target which we don't allow.\n",
  552.         devPtr->handle.locationName);
  553.     status = FAILURE;
  554.     }
  555.     if (interruptReg & IR_RESLCT) {
  556.     PerformReselect(ctrlPtr, interruptReg);
  557.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  558.     return TRUE;
  559.     }
  560.     if (IS_CTRL_FREE(ctrlPtr)) {
  561.     if (status == SUCCESS)
  562.         panic("SCSIC90: Got interrupt but ctrl is free.\n");
  563.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  564.     return TRUE;
  565.     }
  566.  
  567.  
  568.     /* Where did we come from? */
  569.     switch (devPtr->lastPhase) {
  570.     case PHASE_COMMAND:
  571.     break;
  572.     case PHASE_BUS_FREE:
  573.     /* nothing happening yet. */
  574.     break;
  575.     case PHASE_SELECTION:
  576.     status = PerformSelect(ctrlPtr, interruptReg, sequenceReg);
  577.     break;
  578.     case PHASE_DATA_IN:
  579. #ifdef sun4c
  580.     /* Drain remaining bytes in pack register to memory. */
  581.     dmaRegsPtr->ctrl |= DMA_DRAIN;
  582. #endif
  583.     status = PerformDataXfer(ctrlPtr, interruptReg, statusReg);
  584.     break;
  585.     case PHASE_DATA_OUT:
  586.     status = PerformDataXfer(ctrlPtr, interruptReg, statusReg);
  587.     break;
  588.     case PHASE_STATUS:
  589.     status = PerformStatus(ctrlPtr, interruptReg);
  590.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  591.     return TRUE;
  592.     break;
  593.     case PHASE_MSG_OUT:
  594.     break;
  595.     case PHASE_MSG_IN:
  596.     status = PerformMsgIn(ctrlPtr);
  597.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  598.     return TRUE;
  599.     break;
  600.     case PHASE_STAT_MSG_IN:
  601.     if (!(interruptReg & IR_DISCNCT)) {
  602.         printf("SCSIC90: Should have seen end of I/O.\n");
  603.         status = FAILURE;
  604.     }
  605.     break;
  606.     case PHASE_RDY_DISCON:
  607.     if (interruptReg & IR_DISCNCT) {
  608.         PUTCIRCBUF(CSTR,"intr: targ ");
  609.         PUTCIRCBUF(CBYTE, (char *)devPtr->targetID);
  610.         PUTCIRCBUF(CSTR," discon.");
  611.         PUTCIRCNULL;
  612.         devPtr->lastPhase = PHASE_BUS_FREE;
  613.         SET_CTRL_FREE(ctrlPtr);
  614.         PerformCmdDone(ctrlPtr,status);
  615.         MASTER_UNLOCK(&(ctrlPtr->mutex));
  616.         return TRUE;
  617.     } else {
  618.         printf("SCSIC90: expecting disconnect signal.\n");
  619.         status = FAILURE;
  620.     }
  621.     break;
  622.     default:
  623.     /* We set this field, so this shouldn't happen. */
  624.     printf("SCSIC90Intr: We came from an unknown phase.\n");
  625.     status = FAILURE;
  626.     break;
  627.     }
  628.  
  629.     if ((status != SUCCESS) || (interruptReg & IR_DISCNCT)) {
  630.         PUTCIRCBUF(CSTR,"intr: exit stat ");
  631.         PUTCIRCBUF(CBYTE,(char *)status);
  632.         PUTCIRCNULL;
  633.     RequestDone(devPtr,
  634.             devPtr->scsiCmdPtr,
  635.             status,
  636.             devPtr->commandStatus,
  637.             devPtr->scsiCmdPtr->bufferLen - devPtr->activeBufLen);
  638.     PerformCmdDone(ctrlPtr,status);
  639.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  640.     return TRUE;
  641.     }
  642.  
  643.     switch (phase) {
  644.  
  645.     case SR_DATA_OUT:
  646.     case SR_DATA_IN:
  647.     devPtr->lastPhase = (phase == SR_DATA_OUT ? PHASE_DATA_OUT :
  648.                  PHASE_DATA_IN);
  649.     /*
  650.      * It should be possible to do multiple blocks of DMA without
  651.      * returning to the higher level, if we set the max transfer size
  652.      * larger, but we don't handle that yet. XXX
  653.      */
  654. #ifdef sun4c
  655.     dmaControllerActive++;    /* Resetting controller not allowed. */
  656. #endif
  657.     PUTCIRCBUF(CSTR,"start dma ptr: ");
  658.     PUTCIRCBUF(CINT,(char *)devPtr->activeBufPtr);
  659.     PUTCIRCBUF(CSTR,"; len: ");
  660.     PUTCIRCBUF(CINT,(char *)devPtr->activeBufLen);
  661.     PUTCIRCNULL;
  662.     DevStartDMA(ctrlPtr);
  663.     break;
  664.     case SR_COMMAND:
  665.     charPtr = devPtr->scsiCmdPtr->commandBlock;
  666.     PUTCIRCBUF(CSTR,"cmd:");
  667.     for (i = 0; i < devPtr->scsiCmdPtr->commandBlockLen; i++) {
  668.         circBuf[circHead] = ' ';
  669.         circHead = (circHead + 1) % CIRCBUFLEN;
  670.         PUTCIRCBUF(CBYTE, (char *)*charPtr);
  671.         regsPtr->scsi_ctrl.write.FIFO = *charPtr;
  672.         charPtr++;
  673.     }
  674.     PUTCIRCNULL;
  675.     devPtr->lastPhase = PHASE_COMMAND;
  676.     regsPtr->scsi_ctrl.write.synchPer = devPtr->synchPeriod;
  677.     regsPtr->scsi_ctrl.write.synchOffset = devPtr->synchOffset;
  678.     regsPtr->scsi_ctrl.write.command = CR_XFER_INFO;
  679.     break;
  680.     case SR_STATUS:
  681.     /*
  682.      * We're in status phase.  If all goes right, the next interrupt
  683.      * will be after we've handled the message phase as well, although
  684.      * the phase will say we're in message phase.
  685.      */
  686.     devPtr->lastPhase = PHASE_STATUS;
  687.     regsPtr->scsi_ctrl.write.command = CR_INIT_COMP;
  688.     break;
  689.     case SR_MSG_OUT:
  690.     i = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  691.     if (i > 0) {
  692.         PUTCIRCBUF(CSTR,"msg-out: fifo: ");
  693.         while (i-- > 0) {
  694.         circBuf[circHead] = ' ';
  695.         circHead = (circHead + 1) % CIRCBUFLEN;
  696.         tempChar = regsPtr->scsi_ctrl.read.FIFO;
  697.         PUTCIRCBUF(CBYTE,(char*)(tempChar));
  698.         }
  699.         PUTCIRCNULL;
  700.     }
  701.     PUTCIRCBUF(CSTR,"msg-out: msg: ");
  702.     for (i=0; i<devPtr->messageBufLen; i++) {
  703.         circBuf[circHead] = ' ';
  704.         circHead = (circHead + 1) % CIRCBUFLEN;
  705.         PUTCIRCBUF(CBYTE, (char *)devPtr->messageBuf[i]);
  706.         regsPtr->scsi_ctrl.write.FIFO = devPtr->messageBuf[i];
  707.         devPtr->messageBuf[i] = '\0';
  708.     }
  709.     PUTCIRCNULL;
  710.     regsPtr->scsi_ctrl.write.command = CR_XFER_INFO;
  711.     devPtr->lastPhase = PHASE_MSG_OUT;
  712.     devPtr->messageBufLen = 0;
  713.     status = regsPtr->scsi_ctrl.read.status;
  714.     if (status & SR_GE) {
  715.         panic("gross error 2");
  716.     }
  717.     break;
  718.     case SR_MSG_IN:
  719.     /* request incoming message xfer */
  720.     regsPtr->scsi_ctrl.write.command = CR_XFER_INFO;
  721.     devPtr->lastPhase = PHASE_MSG_IN;
  722.     break;
  723.     default:
  724.     printf("unknown scsi phase type: 0x%02x\n", (int)phase);
  725.     status = FAILURE;
  726.     break;
  727.     }
  728.  
  729.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  730.     return TRUE;
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * PerformCmdDone
  737.  *
  738.  *    Do cleanup after final phase of command.
  739.  *
  740.  * Results:
  741.  *    None.
  742.  *
  743.  * Side effects:
  744.  *    Calls RequestDone routine to invoke callback
  745.  *      and then gets next item of queue set.
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */
  749. /*ARGSUSED*/
  750. static void
  751. PerformCmdDone(ctrlPtr,status)
  752.     Controller   *ctrlPtr;
  753.     ReturnStatus status;
  754. {
  755.     List_Links        *newRequestPtr;
  756.     ClientData        clientData;
  757.  
  758.     ctrlPtr->regsPtr->scsi_ctrl.write.command = CR_EN_SLCT;
  759.     if (IS_CTRL_FREE(ctrlPtr)) {
  760.     if (ctrlPtr->interruptDevPtr == (Device *)NIL) {
  761.         newRequestPtr = Dev_QueueGetNextFromSet(ctrlPtr->devQueues,
  762.                         ctrlPtr->devQueuesMask,
  763.                         &clientData);
  764.         PUTCIRCBUF(CSTR,"cdone: cmd ");
  765.         PUTCIRCBUF(CINT,(char *)newRequestPtr);
  766.         PUTCIRCNULL;
  767.     } else {
  768.         clientData = (ClientData)(ctrlPtr->interruptDevPtr);
  769.         newRequestPtr=(List_Links *)(ctrlPtr->interruptDevPtr->scsiCmdPtr);
  770.         SET_DEV_FREE(ctrlPtr->interruptDevPtr);
  771.         ctrlPtr->interruptDevPtr = (Device *)NIL;
  772.         PUTCIRCBUF(CSTR,"cdone: resend dev ");
  773.         PUTCIRCBUF(CINT, (char *)clientData);
  774.         PUTCIRCBUF(CSTR," cmd ");
  775.         PUTCIRCBUF(CINT,(char *)newRequestPtr);
  776.         PUTCIRCNULL;
  777.     }
  778.     if (newRequestPtr != (List_Links *) NIL) {
  779.         (void) DevEntryAvailProc(clientData, newRequestPtr);
  780.     }
  781.     } else {
  782.     PUTCIRCBUF(CSTR,"cdone: busy ");
  783.     PUTCIRCNULL;
  784.     }
  785.  
  786. }
  787.  
  788. /*
  789.  *----------------------------------------------------------------------
  790.  *
  791.  * PerformSelect
  792.  *
  793.  *    Interpret select phase
  794.  *
  795.  * Results:
  796.  *    None.
  797.  *
  798.  * Side effects:
  799.  *    None.
  800.  *
  801.  *----------------------------------------------------------------------
  802.  */
  803. static ReturnStatus
  804. PerformSelect(ctrlPtr, interruptReg, sequenceReg)
  805. Controller      *ctrlPtr;
  806. unsigned int    interruptReg;
  807. unsigned int    sequenceReg;
  808. {
  809.     Device   *devPtr = ctrlPtr->devPtr;
  810.     static char *errMsg[] = {
  811.     "No error",
  812.     "target timed out",
  813.     "no message-out phase",
  814.     "no command phase",
  815.     "command phase incomplete",
  816.     "unknown sequence error"
  817.     };
  818.     int msgNum;
  819.     ReturnStatus status = SUCCESS;
  820.  
  821.     switch(sequenceReg) {
  822.     case SEQ_COMPLETE:
  823.     msgNum = 0;
  824.     break;
  825.     case SEQ_NO_SEL:
  826.     if (interruptReg & IR_DISCNCT) {
  827.         msgNum = 1;
  828.         status = DEV_NO_DEVICE;
  829.     } else if (!(devPtr->msgFlag & REQEXTENDEDMSG)) {
  830.         msgNum = 2;
  831.     } else {
  832.         msgNum = 0;
  833.         devPtr->msgFlag &= ~REQEXTENDEDMSG;
  834.         devPtr->messageBuf[0] = SCSI_EXTENDED_MESSAGE;
  835.         devPtr->messageBuf[1] = 3;
  836.         devPtr->messageBuf[2] = SCSI_EXTENDED_MSG_SYNC;
  837.         devPtr->messageBuf[3] = NCR_TO_SCSI(MIN_SYNCH_PERIOD);
  838.         devPtr->messageBuf[4] = MAX_SYNCH_OFFSET;
  839.         devPtr->messageBufLen = 5;
  840.     }
  841.     break;
  842.     case SEQ_NO_CMD:
  843.     msgNum = 3;
  844.     break;
  845.     case SEQ_CMD_INCOMPLETE:
  846.     msgNum = 4;
  847.     break;
  848.     default:
  849.     msgNum = 5;
  850.     break;
  851.     }
  852.     
  853.     if (msgNum) {
  854.     ctrlPtr->regsPtr->scsi_ctrl.write.command = CR_FLSH_FIFO;
  855.     if (status == SUCCESS) {
  856.         status = FAILURE;
  857.     }
  858.     }
  859.     
  860.     return status;
  861.  
  862.  
  863. /*
  864.  *----------------------------------------------------------------------
  865.  *
  866.  * PerformDataXfer
  867.  *
  868.  *    Interpret data-in, data-out condition
  869.  *
  870.  * Results:
  871.  *    None.
  872.  *
  873.  * Side effects:
  874.  *    None.
  875.  *
  876.  *----------------------------------------------------------------------
  877.  */
  878. /*ARGSUSED*/
  879. static ReturnStatus
  880. PerformDataXfer(ctrlPtr, interruptReg, statusReg)
  881.     Controller      *ctrlPtr;
  882.     unsigned int    interruptReg;
  883.     unsigned int    statusReg;
  884. {
  885.     ReturnStatus status = SUCCESS;
  886.     volatile CtrlRegs    *regsPtr = ctrlPtr->regsPtr;
  887.     Device         *devPtr = ctrlPtr->devPtr;
  888.     unsigned char  fifoCnt;
  889.     int            residual;
  890.     int           amountXfered;
  891.  
  892.     if (interruptReg & IR_DISCNCT) {
  893.     printf("%s disconnected or timed out during data xfer.\n",
  894.            devPtr->handle.locationName);
  895.     return DEV_TIMEOUT;
  896.     }
  897.  
  898. #ifdef sun4c
  899.     dmaControllerActive--;
  900.     MACH_DELAY(100);
  901. #endif
  902.     residual = regsPtr->scsi_ctrl.read.xCntLo;
  903. #ifdef sun4c
  904.     MACH_DELAY(100);
  905. #endif
  906.     residual += (regsPtr->scsi_ctrl.read.xCntHi << 8);
  907.     fifoCnt = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  908.     residual += fifoCnt;
  909.     /*
  910.      * If the transfer was the maximum, 64K bytes, a 0 in the counter
  911.      * may mean that nothing was transfered...  What should I do? XXX
  912.      */
  913.  
  914.     PUTCIRCBUF(CSTR,"residual: ");
  915.     PUTCIRCBUF(CINT,(char *)(residual));
  916.     PUTCIRCBUF(CSTR,"; fifoCnt ");
  917.     PUTCIRCBUF(CINT,(char *)(fifoCnt));
  918.     PUTCIRCNULL;
  919.     regsPtr->scsi_ctrl.write.command = CR_FLSH_FIFO;
  920.  
  921.     /*
  922.      * Flush the cache on data in, since the dma put it into memory
  923.      * but didn't go through the cache.  We don't have to worry about this
  924.      * on writes, since the sparcstation has a write-through cache.
  925.      */
  926.     amountXfered = devPtr->activeBufLen - residual;
  927.     if (devPtr->lastPhase == PHASE_DATA_IN) {
  928.     FLUSH_BYTES((char *) ctrlPtr->buffer, devPtr->activeBufPtr, 
  929.             amountXfered);
  930.     }
  931.     devPtr->activeBufPtr += amountXfered;
  932.     devPtr->activeBufLen = residual;
  933.  
  934.     if (! (interruptReg & IR_BUS_SERV)) {
  935.     /* Target didn't request information transfer phase. */
  936.     printf("Didn't receive bus service signal after DMA xfer.\n");
  937.     status = FAILURE;
  938.     }
  939.  
  940.     return status;
  941.  
  942. }
  943.  
  944. /*
  945.  *----------------------------------------------------------------------
  946.  *
  947.  * PerformStatus
  948.  *
  949.  *    Interpret status condition
  950.  *
  951.  * Results:
  952.  *    None.
  953.  *
  954.  * Side effects:
  955.  *    None.
  956.  *
  957.  *----------------------------------------------------------------------
  958.  */
  959. static ReturnStatus
  960. PerformStatus(ctrlPtr, interruptReg)
  961. Controller      *ctrlPtr;
  962. unsigned int    interruptReg;
  963. {
  964.     volatile CtrlRegs    *regsPtr = ctrlPtr->regsPtr;
  965.     Device              *devPtr = ctrlPtr->devPtr;
  966.     int            numBytes;
  967.     unsigned            char message;
  968.  
  969.     devPtr->lastPhase = PHASE_STAT_MSG_IN;
  970.     /* Read bytes from FIFO. */
  971.     numBytes = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  972.     if (numBytes != 2) {
  973.     /* We didn't get both phases. */
  974.     printf("SCSIC90: Missing message byte after status phase byte.\n");
  975.     return(FAILURE);
  976.     }
  977.     devPtr->commandStatus = regsPtr->scsi_ctrl.read.FIFO;
  978.     devPtr->commandStatus &= SCSI_STATUS_MASK;
  979.     message = regsPtr->scsi_ctrl.read.FIFO;
  980.     if (! (interruptReg & IR_FUNC_COMP)) {
  981.     printf("SCSIC90: Command didn't complete.\n");
  982.     return(FAILURE);
  983.     }
  984.  
  985.     if (message != SCSI_COMMAND_COMPLETE) {
  986.     printf("SCSIC90: Expecting cmd_complete msg from %s, got ",
  987.            ctrlPtr->devPtr->handle.locationName);
  988.     PrintMsg((unsigned int) message);
  989.     return(FAILURE);
  990.     }
  991.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  992.     
  993.     return SUCCESS;
  994. }
  995.  
  996. /*
  997.  *----------------------------------------------------------------------
  998.  *
  999.  * PerformMsgIn
  1000.  *
  1001.  *    Interpret msg_in condition
  1002.  *
  1003.  * Results:
  1004.  *    None.
  1005.  *
  1006.  * Side effects:
  1007.  *    None.
  1008.  *
  1009.  *----------------------------------------------------------------------
  1010.  */
  1011. static ReturnStatus
  1012. PerformMsgIn(ctrlPtr)
  1013. Controller *ctrlPtr;
  1014. {
  1015.     ReturnStatus status = SUCCESS;
  1016.     Device *devPtr = ctrlPtr->devPtr;
  1017.     volatile CtrlRegs *regsPtr = ctrlPtr->regsPtr;
  1018.     unsigned char message;
  1019.  
  1020.     message = regsPtr->scsi_ctrl.read.FIFO;
  1021.  
  1022.     PUTCIRCBUF(CSTR,"msg in: ");
  1023.     PUTCIRCBUF(CBYTE, (char *)message);
  1024.     PUTCIRCNULL;
  1025.  
  1026.     if (devPtr->msgFlag & STARTEXTENDEDMSG) { 
  1027.     status = PerformExtendedMsgIn(ctrlPtr,(unsigned int)message);
  1028.     return status;
  1029.     }
  1030.  
  1031.     switch(message) {
  1032.     case SCSI_COMMAND_COMPLETE:
  1033.     /* this is handled in that stat_msg_in phase */
  1034.     printf("not expecting command_complete msg.\n");
  1035.     status = FAILURE;
  1036.     break;
  1037.     case SCSI_DISCONNECT:
  1038.     devPtr->lastPhase = PHASE_RDY_DISCON;
  1039.     break;
  1040.     case SCSI_SAVE_DATA_POINTER:
  1041.     /* No need to save anything since we keep the current
  1042.      * data ptr in activeBufPtr anyway. */
  1043.     devPtr->lastPhase = PHASE_BUS_FREE;
  1044.     PUTCIRCBUF(CSTR,"save: ptr ");
  1045.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufPtr);
  1046.     PUTCIRCBUF(CSTR,"; len ");
  1047.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufLen);
  1048.     PUTCIRCNULL;
  1049.     break;
  1050.     case SCSI_RESTORE_POINTERS:
  1051.     /* No need to restore anything, since we keep the
  1052.      * current data ptr in activeBufPtr anyway. */
  1053.     devPtr->lastPhase = PHASE_BUS_FREE;
  1054.     PUTCIRCBUF(CSTR,"restore: ptr ");
  1055.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufPtr);
  1056.     PUTCIRCBUF(CSTR,"; len ");
  1057.     PUTCIRCBUF(CINT, (char *)devPtr->activeBufLen);
  1058.     PUTCIRCNULL;
  1059.     break;
  1060.     case SCSI_IDENTIFY:
  1061.     devPtr->lastPhase = PHASE_BUS_FREE;
  1062.     break;
  1063.     case SCSI_EXTENDED_MESSAGE:
  1064.     if (devPtr->msgFlag & ENABLEEXTENDEDMSG) {
  1065.         devPtr->msgFlag |= STARTEXTENDEDMSG;
  1066.         status = PerformExtendedMsgIn(ctrlPtr,(unsigned int)message);
  1067.         return status;
  1068.     } else {
  1069.         devPtr->lastPhase = PHASE_MSG_OUT;
  1070.         devPtr->messageBuf[0] = SCSI_MESSAGE_REJECT;
  1071.         devPtr->messageBufLen = 1;
  1072.         regsPtr->scsi_ctrl.write.command = CR_SET_ATN;
  1073.     }
  1074.     break;
  1075.     case SCSI_MESSAGE_REJECT:
  1076.     /* kill any synchronous agreement in effect */
  1077.     devPtr->synchPeriod = MIN_SYNCH_PERIOD;
  1078.     devPtr->synchOffset = 0;
  1079.     devPtr->lastPhase = PHASE_BUS_FREE;
  1080.     devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1081.     break;
  1082.     default:
  1083.     PUTCIRCBUF(CSTR,"Msg-in: unknown msg");
  1084.     PUTCIRCNULL;
  1085.     printf("SCSIC90: Couldn't handle msg type: 0x%02x\n",message);
  1086.     regsPtr->scsi_ctrl.write.command = CR_SET_ATN;
  1087.     devPtr->lastPhase = PHASE_BUS_FREE;
  1088.     break;
  1089.     }
  1090.  
  1091.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  1092.  
  1093.     return status;
  1094.  
  1095. } /* PerformMsgIn */
  1096.  
  1097. /*
  1098.  *----------------------------------------------------------------------
  1099.  *
  1100.  * PerformExtendedMsgIn
  1101.  *
  1102.  *    Interpret extended msg_in condition
  1103.  *
  1104.  * Results:
  1105.  *    status.
  1106.  *
  1107.  * Side effects:
  1108.  *      Sets the values for synchronous xfer in the device structure.
  1109.  *
  1110.  *    We get the bytes of the extended msg 1 at a time.
  1111.  *      Format: extended msg indicator : 0x01 
  1112.  *                       msg length    : 0x?? 
  1113.  *                       msg code      : 0x03 (we only do 1 type) 
  1114.  *                       msg param1    : 0x?? (should be synch_period)
  1115.  *                       msg param2    : 0x?? (should be synch_offset)
  1116.  *
  1117.  *----------------------------------------------------------------------
  1118.  */
  1119. static ReturnStatus
  1120. PerformExtendedMsgIn(ctrlPtr, message)
  1121. Controller *ctrlPtr;
  1122. unsigned int message;
  1123. {
  1124.     ReturnStatus status = SUCCESS;
  1125.     Device *devPtr      = ctrlPtr->devPtr;
  1126.     volatile CtrlRegs *regsPtr = ctrlPtr->regsPtr;
  1127.     int len             = devPtr->messageBufLen;
  1128.     unsigned char periodInClks;
  1129.     unsigned char period;
  1130.     unsigned char offset;
  1131.     int i;
  1132.  
  1133.     devPtr->messageBuf[len] = message;
  1134.     devPtr->messageBufLen++;
  1135.  
  1136.     switch(len) {
  1137.     case 0: /* extended msg code 0x01 */
  1138.     devPtr->lastPhase = PHASE_BUS_FREE;
  1139.     break;
  1140.     case 1: /* msg length. i.e. # bytes to follow this one */
  1141.     devPtr->lastPhase = PHASE_BUS_FREE;
  1142.     break;
  1143.     case 2: /* extended msg code */
  1144.     if ((message != SCSI_EXTENDED_MSG_SYNC) ||
  1145.         (devPtr->messageBuf[1] != 3)) {
  1146.         PUTCIRCBUF(CSTR,"Msg-in: bad xtend msg: ");
  1147.         PUTCIRCBUF(CBYTE,(char *)(message));
  1148.         PUTCIRCBUF(CSTR,"; len ");
  1149.         PUTCIRCBUF(CBYTE,(char *)(devPtr->messageBuf[1]));
  1150.         PUTCIRCNULL;
  1151.         panic("bad xtend msg");
  1152.         devPtr->messageBuf[0] = SCSI_MESSAGE_REJECT;
  1153.         devPtr->messageBufLen = 1;
  1154.         regsPtr->scsi_ctrl.write.command = CR_SET_ATN;
  1155.         devPtr->lastPhase = PHASE_MSG_OUT;
  1156.         devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1157.     } else {
  1158.         devPtr->lastPhase = PHASE_BUS_FREE;
  1159.     }
  1160.     break;
  1161.     case 3: /* synch_period */
  1162.     devPtr->lastPhase = PHASE_BUS_FREE;
  1163.     break;
  1164.     case 4: /* synch_offset */
  1165.     /* 
  1166.      * Now we have both the period and the offset.
  1167.      */
  1168.     period = devPtr->messageBuf[3];
  1169.     offset = devPtr->messageBuf[4];
  1170.     periodInClks = SCSI_TO_NCR(period);
  1171.     /* if values are acceptable, install them else negotiate */
  1172.     if ((periodInClks >= MIN_SYNCH_PERIOD) &&
  1173.         (offset <= MAX_SYNCH_OFFSET)) {
  1174.         PUTCIRCBUF(CSTR,"accept per: ");
  1175.         PUTCIRCBUF(CBYTE,(char *)period);
  1176.         PUTCIRCBUF(CSTR,"; per clk ");
  1177.         PUTCIRCBUF(CBYTE,(char *)periodInClks);
  1178.         PUTCIRCBUF(CSTR,"; off ");
  1179.         PUTCIRCBUF(CBYTE,(char *)offset);
  1180.         PUTCIRCNULL;
  1181.         devPtr->synchPeriod = periodInClks; 
  1182.         devPtr->synchOffset = offset;
  1183.         devPtr->lastPhase = PHASE_BUS_FREE;
  1184.         devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1185.     } else {
  1186.         if (periodInClks < devPtr->synchPeriod) {
  1187.         devPtr->messageBuf[3] = NCR_TO_SCSI(MIN_SYNCH_PERIOD);
  1188.         }
  1189.         if (offset > devPtr->synchOffset) {
  1190.         devPtr->messageBuf[4] = MAX_SYNCH_OFFSET;
  1191.         }
  1192.         PUTCIRCBUF(CSTR,"negotiate per: ");
  1193.         PUTCIRCBUF(CBYTE,(char *)(devPtr->messageBuf[3]));
  1194.         PUTCIRCBUF(CSTR,"; off ");
  1195.         PUTCIRCBUF(CBYTE,(char *)(devPtr->messageBuf[4]));
  1196.         PUTCIRCNULL;
  1197.         regsPtr->scsi_ctrl.write.command = CR_SET_ATN;
  1198.         devPtr->lastPhase = PHASE_MSG_OUT;
  1199.         devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1200.     }
  1201.     break;
  1202.     default:
  1203.     printf("SCSIC90: xmsg case error\n");
  1204.     devPtr->msgFlag &= ~STARTEXTENDEDMSG;
  1205.     status = FALSE;
  1206.     break;
  1207.     }
  1208.     PUTCIRCBUF(CSTR,"Xmsg-in: accept msg");
  1209.     len = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  1210.     PUTCIRCBUF(CSTR,"; FIFO:");
  1211.     for(i=0;i<len;i++) {
  1212.     circBuf[circHead] = ' ';
  1213.     circHead = (circHead + 1) % CIRCBUFLEN;
  1214.     offset = regsPtr->scsi_ctrl.read.FIFO;
  1215.     PUTCIRCBUF(CBYTE, (char *)offset);
  1216.     }
  1217.     PUTCIRCBUF(CSTR,"; mbuf:");
  1218.     for(i=0;i<devPtr->messageBufLen;i++) {
  1219.     circBuf[circHead] = ' ';
  1220.     circHead = (circHead + 1) % CIRCBUFLEN;
  1221.     PUTCIRCBUF(CBYTE, (char *)(devPtr->messageBuf[i]));
  1222.     }
  1223.     PUTCIRCNULL;
  1224.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  1225.     return status;
  1226.  
  1227. /*
  1228.  *----------------------------------------------------------------------
  1229.  *
  1230.  * PerformReselect
  1231.  *
  1232.  *    Reconnect a logical unit
  1233.  *
  1234.  * Results:
  1235.  *    None.
  1236.  *
  1237.  * Side effects:
  1238.  *    None.
  1239.  *
  1240.  *----------------------------------------------------------------------
  1241.  */
  1242. static ReturnStatus
  1243. PerformReselect(ctrlPtr, interruptReg)
  1244. Controller      *ctrlPtr;
  1245. unsigned int    interruptReg;
  1246. {
  1247.     volatile CtrlRegs *regsPtr = ctrlPtr->regsPtr;
  1248.     Device            *devPtr;
  1249.     unsigned char     target;
  1250.     unsigned char     ourID;
  1251.     unsigned char     message;
  1252.     int               fifoCnt,i;
  1253.  
  1254.     /* The ID of the target which is requesting reselection comes over 
  1255.      * the bus encoded, not 0-7.  The encoding is the logical OR of 
  1256.      * two bytes: one with the i'th bit set (for target #i) and
  1257.      * one with the host's bit set (usually #7). Unfortunately,
  1258.      * the host's ID is kindly provided to us in binary so we perform
  1259.      * a little transformation...
  1260.      */
  1261.     target = regsPtr->scsi_ctrl.read.FIFO;
  1262.     ourID = regsPtr->scsi_ctrl.read.config1 & C1_BUS_ID;
  1263.     ourID = ~(1 << ourID);
  1264.  
  1265.     switch(target & ourID) {
  1266.     case 0x01:
  1267.     target = 0;
  1268.     break;
  1269.     case 0x02:
  1270.     target = 1;
  1271.     break;
  1272.     case 0x04:
  1273.     target = 2;
  1274.     break;
  1275.     case 0x08:
  1276.     target = 3;
  1277.     break;
  1278.     case 0x10:
  1279.     target = 4;
  1280.     break;
  1281.     case 0x20:
  1282.     target = 5;
  1283.     break;
  1284.     case 0x40:
  1285.     target = 6;
  1286.     break;
  1287.     case 0x80:
  1288.     target = 7;
  1289.     break;
  1290.     default:
  1291.     printf("SCSIC90: couldn't decode target ID 0x%02x\n", target);
  1292.     return FAILURE;
  1293.     }
  1294.  
  1295.     message = regsPtr->scsi_ctrl.read.FIFO;    
  1296.  
  1297.     if (!(message & SCSI_IDENTIFY)) {
  1298.     printf("SCSIC90: Expected Identify msg after reselect, got 0x%02x.\n",
  1299.            message);
  1300.     return FAILURE;
  1301.     }
  1302.     message &= SCSI_IDENT_LUN_MASK;
  1303.  
  1304.     devPtr = ctrlPtr->devicePtr[target][message];
  1305.  
  1306.     fifoCnt = regsPtr->scsi_ctrl.read.FIFOFlags & FIFO_BYTES_MASK;
  1307.     PUTCIRCBUF(CSTR,"resel: targ ");
  1308.     PUTCIRCBUF(CBYTE, (char *)target);
  1309.     PUTCIRCBUF(CSTR,"; lun ");
  1310.     PUTCIRCBUF(CBYTE, (char *)message);
  1311.     ourID = regsPtr->scsi_ctrl.read.command;
  1312.     PUTCIRCBUF(CSTR,"; cmdreg:");
  1313.     PUTCIRCBUF(CBYTE,(char *)ourID);
  1314.     PUTCIRCBUF(CSTR,"; FIFO:");
  1315.     for(i=0;i<fifoCnt;i++) {
  1316.     circBuf[circHead] = ' ';
  1317.     circHead = (circHead + 1) % CIRCBUFLEN;
  1318.     ourID = regsPtr->scsi_ctrl.read.FIFO;
  1319.     PUTCIRCBUF(CBYTE, (char *)ourID);
  1320.     }
  1321.     PUTCIRCNULL;
  1322.  
  1323.     if (IS_DEV_FREE(devPtr)) {
  1324.     panic("resel: device is free.\n");
  1325.     }
  1326.  
  1327.     /*
  1328.      * It's possible for the reselection interrupt to occur just
  1329.      * when we were sending a new command.  Three cases:
  1330.      *  1) Interrupt happened before loading any cmd bytes.
  1331.      *     Only indication is that controller is busy.
  1332.      *  2) Interrupt happened before the send; part of the
  1333.      *     cmd in the fifo.
  1334.      *  3) Interrupt happened during the arbitration/selection
  1335.      *     phases of the send; the bus_serv bit will be set.
  1336.      * Note that the 53C90 doesn't handle this situation quite
  1337.      * the same as the later 53C94, 53C95 chips. The older chip
  1338.      * accepts cmd bytes after it shouldn't so there may be bytes
  1339.      * in the FIFO now that should be here. See the manual.
  1340.      */
  1341.  
  1342.  
  1343.     /* An restore_data_ pointer cmd is implied by a reselect
  1344.      * but we don't need to do anything */
  1345.     regsPtr->scsi_ctrl.write.command = CR_MSG_ACCPT;
  1346.  
  1347.     if (!(IS_CTRL_FREE(ctrlPtr)) ||
  1348.     (interruptReg & IR_BUS_SERV) ||
  1349.     (fifoCnt > 0)) {
  1350.     PUTCIRCBUF(CSTR,"resel: save dev ");
  1351.     PUTCIRCBUF(CINT, (char *)ctrlPtr->devPtr);
  1352.     PUTCIRCBUF(CSTR," cmd ");
  1353.     PUTCIRCBUF(CINT, (char *)ctrlPtr->devPtr->scsiCmdPtr);
  1354.     PUTCIRCNULL;
  1355.     ctrlPtr->interruptDevPtr = ctrlPtr->devPtr;
  1356.     regsPtr->scsi_ctrl.write.command = CR_FLSH_FIFO;
  1357.     }
  1358.  
  1359.     SET_CTRL_BUSY(ctrlPtr,devPtr);
  1360.  
  1361.     return SUCCESS;
  1362. }
  1363.  
  1364. /*
  1365.  *----------------------------------------------------------------------
  1366.  *
  1367.  * ReleaseProc --
  1368.  *
  1369.  *    Device release proc for controller.
  1370.  *
  1371.  * Results:
  1372.  *    None.
  1373.  *
  1374.  * Side effects:
  1375.  *    None.
  1376.  *
  1377.  *----------------------------------------------------------------------
  1378.  */
  1379. /*ARGSUSED*/
  1380. static ReturnStatus
  1381. ReleaseProc(scsiDevicePtr)
  1382.     ScsiDevice    *scsiDevicePtr;
  1383. {
  1384.     return SUCCESS;
  1385. }
  1386.  
  1387.  
  1388. /*
  1389.  *----------------------------------------------------------------------
  1390.  *
  1391.  * DevSCSIC90AttachDevice --
  1392.  *
  1393.  *    Attach a SCSI device using the Sun SCSIC90 HBA. 
  1394.  *
  1395.  * Results:
  1396.  *    None.
  1397.  *
  1398.  * Side effects:
  1399.  *    None.
  1400.  *
  1401.  *----------------------------------------------------------------------
  1402.  */
  1403.  
  1404. ScsiDevice   *
  1405. DevSCSIC90AttachDevice(devicePtr, insertProc)
  1406.     Fs_Device    *devicePtr;     /* Device to attach. */
  1407.     void    (*insertProc)(); /* Queue insert procedure. */
  1408. {
  1409.     Device *devPtr;
  1410.     Controller    *ctrlPtr;
  1411.     char   tmpBuffer[512];
  1412.     int       length;
  1413.     int       ctrlNum;
  1414.     int       targetID, lun;
  1415.  
  1416.     /*
  1417.      * First find the SCSIC90 controller this device is on.
  1418.      */
  1419.     ctrlNum = SCSI_HBA_NUMBER(devicePtr);
  1420.     if ((ctrlNum > MAX_SCSIC90_CTRLS) ||
  1421.     (Controllers[ctrlNum] == (Controller *) 0)) { 
  1422.     return (ScsiDevice  *) NIL;
  1423.     } 
  1424.     ctrlPtr = Controllers[ctrlNum];
  1425.     targetID = SCSI_TARGET_ID(devicePtr);
  1426.     lun = SCSI_LUN(devicePtr);
  1427.     /*
  1428.      * Allocate a device structure for the device and fill in the
  1429.      * handle part. This must be created before we grap the MASTER_LOCK.
  1430.      */
  1431.     devPtr = (Device *) malloc(sizeof(Device)); 
  1432.     bzero((char *) devPtr, sizeof(Device));
  1433.     devPtr->handle.devQueue = Dev_QueueCreate(ctrlPtr->devQueues,
  1434.                           (1<<targetID),
  1435.                           insertProc,
  1436.                           (ClientData) devPtr);
  1437.     devPtr->handle.locationName = "Unknown";
  1438.     devPtr->handle.LUN = lun;
  1439.     devPtr->handle.releaseProc = ReleaseProc;
  1440.     devPtr->handle.maxTransferSize = MAX_TRANSFER_SIZE;
  1441.     devPtr->targetID = targetID;
  1442.     devPtr->ctrlPtr = ctrlPtr;
  1443.     devPtr->synchPeriod = 0;
  1444.     devPtr->synchOffset = 0;
  1445.     devPtr->msgFlag = 0;
  1446.     MASTER_LOCK(&(ctrlPtr->mutex));
  1447.     /*
  1448.      * A device pointer of zero means that targetID/LUN 
  1449.      * conflicts with that of the HBA. A NIL means the
  1450.      * device hasn't been attached yet.
  1451.      */
  1452.     if (ctrlPtr->devicePtr[targetID][lun] == (Device *) 0) {
  1453.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1454.     (void) Dev_QueueDestroy(devPtr->handle.devQueue);
  1455.     free((char *) devPtr);
  1456.     return (ScsiDevice *) NIL;
  1457.     }
  1458.     if (ctrlPtr->devicePtr[targetID][lun] != (Device *) NIL) {
  1459.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1460.     (void) Dev_QueueDestroy(devPtr->handle.devQueue);
  1461.     free((char *) devPtr);
  1462.     return (ScsiDevice *) (ctrlPtr->devicePtr[targetID][lun]);
  1463.     }
  1464.     SET_DEV_FREE(devPtr);
  1465.     ctrlPtr->devicePtr[targetID][lun] = devPtr;
  1466.     MASTER_UNLOCK(&(ctrlPtr->mutex));
  1467.     (void) sprintf(tmpBuffer, "%s Target %d LUN %d", ctrlPtr->name, 
  1468.             devPtr->targetID, devPtr->handle.LUN);
  1469.     length = strlen(tmpBuffer);
  1470.     devPtr->handle.locationName = (char *) strcpy(malloc(length+1),tmpBuffer);
  1471.  
  1472.     if (devSCSIC90Debug > 3) {
  1473.     printf("devSCSIC90Attach: attached device %s.\n", tmpBuffer);
  1474.     }
  1475.  
  1476.     return (ScsiDevice *) devPtr;
  1477. }
  1478.  
  1479.  
  1480. /*
  1481.  *----------------------------------------------------------------------
  1482.  *
  1483.  * PrintMsg --
  1484.  *
  1485.  *    Print out the asci string for a scsi msg.
  1486.  *
  1487.  * Results:
  1488.  *    None.
  1489.  *
  1490.  * Side effects:
  1491.  *    None.
  1492.  *
  1493.  *----------------------------------------------------------------------
  1494.  */
  1495. static void
  1496. PrintMsg(msg)
  1497.     unsigned int msg;
  1498. {
  1499.  
  1500.     if (msg & SCSI_IDENTIFY) {
  1501.     if (msg & SCSI_DIS_REC_IDENTIFY) {
  1502.         printf("dis_rec_identify (LUN 0x%02x) msg.\n",
  1503.            (int)(msg & SCSI_IDENT_LUN_MASK));
  1504.     } else {
  1505.         printf("identify (LUN 0x%02x) msg.\n",
  1506.            (int)(msg & SCSI_IDENT_LUN_MASK));
  1507.     }
  1508.     return;
  1509.     } 
  1510.  
  1511.     switch (msg) {
  1512.     case SCSI_COMMAND_COMPLETE:
  1513.     printf("command_complete msg.\n");
  1514.     break;
  1515.     case SCSI_SAVE_DATA_POINTER:
  1516.     printf("save_data_ptr msg.\n");
  1517.     break;
  1518.     case SCSI_RESTORE_POINTERS:
  1519.     printf("restore_ptrs msg.\n");
  1520.     break;
  1521.     case SCSI_DISCONNECT:
  1522.     printf("disconnect msg.\n");
  1523.     break;
  1524.     case SCSI_ABORT:
  1525.     printf("abort msg.\n");
  1526.     break;
  1527.     case SCSI_MESSAGE_REJECT:
  1528.     printf("msg_reject msg.\n");
  1529.     break;
  1530.     case SCSI_NO_OP:
  1531.     printf("no_op msg.\n");
  1532.     break;
  1533.     case SCSI_MESSAGE_PARITY_ERROR:
  1534.     printf("msg_parity msg.\n");
  1535.     break;
  1536.     case SCSI_BUS_RESET:
  1537.     printf("bus_reset msg.\n");
  1538.     break;
  1539.     default:
  1540.     printf("unknown msg %d.\n", msg);
  1541.     break;
  1542.     }
  1543.  
  1544.     return;
  1545. }
  1546.  
  1547. #ifndef lint
  1548.  
  1549. /*
  1550.  *----------------------------------------------------------------------
  1551.  *
  1552.  * PrintPhase --
  1553.  *
  1554.  *    Print out the asci string for a scsi phase.
  1555.  *
  1556.  * Results:
  1557.  *    None.
  1558.  *
  1559.  * Side effects:
  1560.  *    None.
  1561.  *
  1562.  *----------------------------------------------------------------------
  1563.  */
  1564. static void
  1565. PrintPhase(phase)
  1566.     unsigned int    phase;
  1567. {
  1568.     
  1569.     switch (phase) {
  1570.     case SR_DATA_OUT:
  1571.     printf("data out phase.\n");
  1572.     break;
  1573.     case SR_DATA_IN:
  1574.     printf("data in phase.\n");
  1575.     break;
  1576.     case SR_COMMAND:
  1577.     printf("command phase.\n");
  1578.     break;
  1579.     case SR_STATUS:
  1580.     printf("status phase.\n");
  1581.     break;
  1582.     case SR_MSG_OUT:
  1583.     printf("msg out phase.\n");
  1584.     break;
  1585.     case SR_MSG_IN:
  1586.     printf("msg in phase.\n");
  1587.     break;
  1588.     default:
  1589.     printf("unknown phase %d.\n", phase);
  1590.     break;
  1591.     }
  1592.  
  1593.     return;
  1594. }
  1595.  
  1596. /*
  1597.  *----------------------------------------------------------------------
  1598.  *
  1599.  * PrintLastPhase --
  1600.  *
  1601.  *    Print out the asci string for the last scsi phase we were in.
  1602.  *
  1603.  * Results:
  1604.  *    None.
  1605.  *
  1606.  * Side effects:
  1607.  *    None.
  1608.  *
  1609.  *----------------------------------------------------------------------
  1610.  */
  1611. static void
  1612. PrintLastPhase(phase)
  1613.     unsigned int    phase;
  1614. {
  1615.     switch (phase) {
  1616.     case PHASE_BUS_FREE:
  1617.     printf("bus free phase.\n");
  1618.     break;
  1619.     case PHASE_SELECTION:
  1620.     printf("selection phase.\n");
  1621.     break;
  1622.     case PHASE_DATA_OUT:
  1623.     printf("data out phase.\n");
  1624.     break;
  1625.     case PHASE_DATA_IN:
  1626.     printf("data in phase.\n");
  1627.     break;
  1628.     case PHASE_STATUS:
  1629.     printf("status phase.\n");
  1630.     break;
  1631.     case PHASE_MSG_IN:
  1632.     printf("msg in phase.\n");
  1633.     break;
  1634.     case PHASE_STAT_MSG_IN:
  1635.     printf("stat_msg in phase.\n");
  1636.     break;
  1637.     case PHASE_RDY_DISCON:
  1638.     printf("rdy_discon phase.\n");
  1639.     break;
  1640.     default:
  1641.     printf("unknown phase %d.\n", phase);
  1642.     break;
  1643.     }
  1644.  
  1645.     return;
  1646. }
  1647.  
  1648. /*
  1649.  *----------------------------------------------------------------------
  1650.  *
  1651.  * PrintRegs --
  1652.  *
  1653.  *    Print out the interesting registers.  This could be a macro but
  1654.  *    then it couldn't be called from kdbx.  This routine is necessary
  1655.  *    because kdbx doesn't print all the character values properly.
  1656.  *
  1657.  * Results:
  1658.  *    None.
  1659.  *
  1660.  * Side effects:
  1661.  *    Data is displayed on the console or to the debugger.
  1662.  *
  1663.  *----------------------------------------------------------------------
  1664.  */
  1665. static void
  1666. PrintRegs(regsPtr)
  1667.     register volatile CtrlRegs *regsPtr;
  1668. {
  1669.  
  1670.     printf("Won't print interrupt register since that would clear it.\n");
  1671.     printf("xCntLow: 0x%x, xCntHi: 0x%x, FIFO: 0x%x, command: 0x%x,\n",
  1672.         regsPtr->scsi_ctrl.read.xCntLo,
  1673.         regsPtr->scsi_ctrl.read.xCntHi,
  1674.         regsPtr->scsi_ctrl.read.FIFO,
  1675.         regsPtr->scsi_ctrl.read.command);
  1676.     printf("status: 0x%x, sequence: 0x%x, FIFOFlags: 0x%x, config1: 0x%x,\n",
  1677.         regsPtr->scsi_ctrl.read.status,
  1678.         regsPtr->scsi_ctrl.read.sequence,
  1679.         regsPtr->scsi_ctrl.read.FIFOFlags,
  1680.         regsPtr->scsi_ctrl.read.config1);
  1681.     printf("config2: 0x%x, config3: 0x%x\n",
  1682.         regsPtr->scsi_ctrl.read.config2,
  1683.         regsPtr->scsi_ctrl.read.config3);
  1684.  
  1685.     return;
  1686. }
  1687. #endif /* LINT */
  1688.  
  1689. /*
  1690.  *----------------------------------------------------------------------
  1691.  *
  1692.  *  SpecialSenseProc --
  1693.  *
  1694.  *    Special function used for HBA generated REQUEST SENSE. A SCSI
  1695.  *    command request with this function as a call back proc will
  1696.  *    be processed by routine RequestDone as a result of a 
  1697.  *    REQUEST SENSE. This routine is never called.
  1698.  *
  1699.  * Results:
  1700.  *    None.
  1701.  *
  1702.  * Side effects:
  1703.  *    None.
  1704.  *
  1705.  *----------------------------------------------------------------------
  1706.  */
  1707. /*ARGSUSED*/
  1708. static int
  1709. SpecialSenseProc(scsiCmdPtr, status, statusByte, byteCount, senseLength,
  1710.          senseDataPtr)
  1711.     ScsiCmd        *scsiCmdPtr;
  1712.     ReturnStatus    status;
  1713.     unsigned char    statusByte;
  1714.     int            byteCount;
  1715.     int            senseLength;
  1716.     Address        senseDataPtr;
  1717. {
  1718.     return 0;
  1719. }
  1720.  
  1721.  
  1722. /*
  1723.  *----------------------------------------------------------------------
  1724.  *
  1725.  * Dev_ChangeScsiDebugLevel --
  1726.  *
  1727.  *    Change the level of debugging info for this scsi driver.
  1728.  *
  1729.  * Results:
  1730.  *    None.
  1731.  *
  1732.  * Side effects:
  1733.  *    A larger or lesser number of messages will be printed out.
  1734.  *
  1735.  *----------------------------------------------------------------------
  1736.  */
  1737. void
  1738. Dev_ChangeScsiDebugLevel(level)
  1739.     int    level;
  1740. {
  1741.     
  1742.     printf("Changing scsi debug level: was %d, ", devSCSIC90Debug);
  1743.     devSCSIC90Debug = level;
  1744.     printf("and is now %d.\n", devSCSIC90Debug);
  1745.  
  1746.     return;
  1747. }
  1748.  
  1749.  
  1750. /*
  1751.  *----------------------------------------------------------------------
  1752.  *
  1753.  * PutCircBuf
  1754.  *
  1755.  *    Stuff data into the circular log buffer
  1756.  *
  1757.  * Results:
  1758.  *    None.
  1759.  *
  1760.  * Side effects:
  1761.  *      None.
  1762.  *
  1763.  *----------------------------------------------------------------------
  1764.  */
  1765. static void
  1766. PutCircBuf(type, object)
  1767. int type;
  1768. char *object;
  1769. {
  1770.     int num = (int)object;
  1771.  
  1772.     switch(type) {
  1773.     case CSTR:
  1774.     while(*object) {
  1775.         circBuf[circHead] = *object++;
  1776.         circHead = (circHead + 1) % CIRCBUFLEN;
  1777.     }
  1778.     break;
  1779.     case CBYTE:
  1780.     circBuf[circHead] = CVTHEX(num,4);
  1781.     circHead = (circHead + 1) % CIRCBUFLEN;
  1782.     circBuf[circHead] = CVTHEX(num,0);
  1783.     circHead = (circHead + 1) % CIRCBUFLEN;
  1784.     break;
  1785.     case CINT:
  1786.     circBuf[circHead] = CVTHEX(num,28); 
  1787.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1788.     circBuf[circHead] = CVTHEX(num,24); 
  1789.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1790.     circBuf[circHead] = CVTHEX(num,20); 
  1791.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1792.     circBuf[circHead] = CVTHEX(num,16); 
  1793.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1794.     circBuf[circHead] = CVTHEX(num,12); 
  1795.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1796.     circBuf[circHead] = CVTHEX(num,8); 
  1797.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1798.     circBuf[circHead] = CVTHEX(num,4); 
  1799.     circHead = (circHead + 1) % CIRCBUFLEN; 
  1800.     circBuf[circHead] = CVTHEX(num,0); 
  1801.     circHead = (circHead + 1) % CIRCBUFLEN;
  1802.     break;
  1803.     default:
  1804.     panic("PutCircBuf: unknown type\n");
  1805.     break;
  1806.     }
  1807. }
  1808.  
  1809.